<?php

declare(strict_types=1);

namespace App\CustHub\Service;

use App\CustHub\Constants\OpSchemeTypeConstants;
use App\CustHub\Constants\RoomWelcomeConstants;
use App\CustHub\Constants\SendConfigConstants;
use App\CustHub\Event\RoomActiveRoom;
use App\CustHub\Helpers\TagReplacer;
use App\CustHub\Mapper\ChOpSchemeMapper;
use App\CustHub\Mapper\ChOpSchemeRobotMapper;
use App\CustHub\Mapper\ChRobotMapper;
use App\CustHub\Mapper\ChRoomMapper;
use App\CustHub\Mapper\ChRoomMemberMapper;
use App\CustHub\Mapper\ChRoomTagMapper;
use App\CustHub\Model\ChRoomMember;
use App\CustHub\Traits\OpSchemeTrait;
use Hyperf\Collection\Collection;
use Hyperf\Collection\Enumerable;
use Hyperf\Di\Annotation\Inject;
use Mine\Abstracts\AbstractService;
use Mine\Exception\NormalStatusException;
use function Hyperf\Collection\collect;
use function Hyperf\Collection\data_get;

class ChRoomWelcomeService extends AbstractService
{
    use OpSchemeTrait;

    public $mapper;

    protected $type = OpSchemeTypeConstants::ROOM_WELCOME;

    #[Inject]
    protected ChRoomMapper $roomMapper;

    #[Inject]
    protected ChRoomTagMapper $roomTagMapper;

    #[Inject]
    protected ChOpSchemeRobotMapper $schemeRobotMapper;

    #[Inject]
    protected ChRoomWelcomeSendService $welcomeSendService;

    #[Inject]
    protected ChRobotMapper $robotMapper;

    #[Inject]
    protected ChSendConfigService $sendConfigService;

    public function __construct(ChOpSchemeMapper $mapper)
    {
        $this->mapper = $mapper;
    }

    public function getInfo(array $params): \Hyperf\Database\Model\Model|\App\CustHub\Model\ChOpScheme|string|\Hyperf\Database\Model\Builder
    {
        $scheme = $this->mapper->findById($params['id']);
        if(empty($scheme)){
            throw new NormalStatusException('请选择方案');
        }

        $cfg = $scheme->cfg;
        $activeRoom = $cfg['active_room'];
        if($activeRoom['type'] == 1){
            //按客户群发送
            $room = $activeRoom['room'];
            $roomList = [];
            foreach ($room as $roomItem){
                $robotId = $roomItem['robot_id'];
                $roomWxids = $roomItem['room_wxids'];
                $robotInfo = $this->robotMapper->findById($robotId);
                $rooms = $this->roomMapper->model::query()
                    ->select(['id','room_name','room_wxid','room_avatar_url'])
                    ->where('main_uid',$params['main_uid'])
                    ->whereIn('room_wxid',$roomWxids)
                    ->get();
                $rooms = $rooms->map(function ($item) use ($robotInfo){
                    return [
                        ...$item->toArray(),
                        'robot_id' => $robotInfo->id ?? '',
                        'robot_nickname' => $robotInfo->nickname ?? '',
                        'robot_avatar' => $robotInfo->avatar ?? '',
                        'robot_user_id' => $robotInfo->user_id ?? ''
                    ];
                })->toArray();
                $roomList = array_merge($roomList,$rooms);
            }
            $cfg['active_room']['room_list'] = $roomList;
            $scheme->cfg = $cfg;
        }elseif($activeRoom['type'] == 2){
            if(!empty($activeRoom['cond']['room_tag']['include_tag_ids'])){
                //按条件筛选
                $roomTagNameList = $this->roomTagMapper->getNameByIds($activeRoom['cond']['room_tag']['include_tag_ids']);
                $cfg['active_room']['cond']['room_tag']['room_tag_name'] = implode(',',$roomTagNameList);
                $scheme->cfg = $cfg;
            }
        }
        return $scheme;
    }

    /**
     * 方案保存后执行
     * @param int $schemeId
     * @param array $data
     * @return void
     * @throws \Psr\Container\ContainerExceptionInterface
     * @throws \Psr\Container\NotFoundExceptionInterface
     */
    public function afterSave(int $schemeId,array $data): void
    {
        event(new RoomActiveRoom([$schemeId],[],OpSchemeTypeConstants::ROOM_WELCOME));
    }

    /**
     * 方案更新后执行
     * @param int $schemeId
     * @param array $data
     * @return void
     * @throws \Psr\Container\ContainerExceptionInterface
     * @throws \Psr\Container\NotFoundExceptionInterface
     */
    public function afterUpdate(int $schemeId,array $data): void
    {
        event(new RoomActiveRoom([$schemeId],[],OpSchemeTypeConstants::ROOM_WELCOME));
    }

    /**
     * 方案删除后执行
     * @param int $schemeId
     * @return void
     * @throws \Psr\Container\ContainerExceptionInterface
     * @throws \Psr\Container\NotFoundExceptionInterface
     */
    public function afterDelete(int $schemeId): void
    {
        event(new RoomActiveRoom([$schemeId],[],OpSchemeTypeConstants::ROOM_WELCOME,false));
    }

    /**
     * 获取客户群列表
     * @param $roomWxIds
     * @return array
     */
    private function getRoomList($roomWxIds): array
    {
        $list = $this->roomMapper->model::query()
            ->select(['id','room_name','room_wxid'])
            ->with(['robots'=>function ($query){
                $query->select(['id','nickname','avatar','corp_name']);
            }])
            ->whereIn('room_wxid',$roomWxIds)
            ->get()->toArray();
        return $list;
    }

    /**
     * 获取满足条件的方案
     * @param mixed $robotId
     * @param string $roomWxid
     * @param mixed $memberCount
     * @return void
     * @throws \RedisException
     */
    public function getMeetTheConditionScheme(int $robotId,int $mainUid,string $roomWxid,int $memberCount,string $roomMemberName,array $changedMemberList): void
    {
        stdout_log()->info('入群欢迎语'.json_encode([
                'room_id' => $roomWxid,
                'member_count' => $memberCount,
                'room_member_name' => $roomMemberName,
                'changed_member_list' => $changedMemberList
            ]));
        $roomInfo = $this->roomMapper->findByRoomWxid($roomWxid,$mainUid);
        if(empty($roomInfo)){
            return;
        }

        //检查当前机器人是否允许发送
        if(!$this->checkRobotAllowSend($robotId)){
            return;
        }

        $robotSchemeList = $this->schemeRobotMapper->findRobotScheme($robotId,$this->type);
        //满足条件的方案
        $condSchemeList = [];
        foreach ($robotSchemeList as $item){
            if(empty($item->scheme)){
                continue;
            }
            $roomWxids = $this->getSchemeRoomWxids($robotId,$item->scheme->cfg['active_room'],$item->main_uid);
            if(!in_array($roomWxid,$roomWxids)){
                continue;
            }
            $item->room_wxids = $roomWxids;
            $condSchemeList[] = $item;
        }

        if(empty($condSchemeList)){
            return;
        }

        $zdRoomSchemeList = collect($condSchemeList)->filter(function ($item){
            return $item->scheme->cfg['active_room']['type'] == 1;
        })->toArray();

        //优先返回指定群的方案
        if(!empty($zdRoomSchemeList)){
            $condScheme = $zdRoomSchemeList[array_rand($zdRoomSchemeList)];
        }else{
            $condScheme = $condSchemeList[array_rand($condSchemeList)];
        }
        $cfg = $condScheme['scheme']['cfg'];
        $triggerCond = $cfg['trigger_cond'];

        $timeSwitch = $triggerCond['time_switch'];
        $numberSwitch = $triggerCond['number_switch'];

        //未发送用户
        $notSentKey = 'room_welcome_not_sent:'.$roomWxid;
        $redis = redis();
        $notSentUserIds = $redis->get($notSentKey);
        if(!empty($notSentUserIds)){
            $changedMemberList = array_unique(array_merge($notSentUserIds,$changedMemberList));
            $notSentRoomMemberName = ChRoomMember::query()
                ->where('room_wxid',$roomWxid)
                ->whereIn('user_id',$changedMemberList)
                ->pluck('nickname')
                ->implode('、');
            if(!empty($notSentRoomMemberName)){
                $roomMemberName = $notSentRoomMemberName .'、'. $roomMemberName;
            }
        }

        $sendMessage = $this->getSendMessageData($cfg);

        $sendMessage = TagReplacer::changeData($sendMessage,[
            'call_name_nickname' => $roomMemberName,
            'receiver' => $changedMemberList
        ]);


        $messageData = [
            'id' => $condScheme['id'],
            'uid' => $condScheme['uid'],
            'main_uid' => $condScheme['main_uid'],
            'content' => $sendMessage
        ];
        if($timeSwitch == 0 && $numberSwitch == 0){
            //触发条件未开启 每进群一人发送一次入群欢迎语
            $this->welcomeSendService->sendWelcomeMessage($robotId,$roomWxid,$messageData,RoomWelcomeConstants::SCENE_MODE_DEFAULT);
        }else{
            $memberThreshold = (int)data_get($triggerCond,'number_cfg',0);
            $timeTriggerThreshold = (int)data_get($triggerCond,'time_cfg',0);
            if ($timeSwitch == 1 && $numberSwitch == 1){
                $scene = RoomWelcomeConstants::SCENE_MODE_BOTH;
            }elseif($timeSwitch == 1){
                $scene = RoomWelcomeConstants::SCENE_MODE_TIME;
            }else{
                $scene = RoomWelcomeConstants::SCENE_MODE_MEMBER;
            }
            $isSend = $this->welcomeSendService->updateRoomData($robotId,$roomWxid,$scene,$messageData,$memberThreshold,$timeTriggerThreshold,$memberCount);

            if(!$isSend){
                $redis->set($notSentKey,$changedMemberList,60 * 60);
            }else{
                $redis->del($notSentKey);
            }
        }

    }

    /**
     * 检查机器人是否允许发送
     * @param mixed $robotId
     * @return bool
     */
    private function checkRobotAllowSend(mixed $robotId): bool
    {
        $robotInfo = $this->robotMapper->findById($robotId);
        if($robotInfo->login_status != 1){
            //机器人离线
            return false;
        }
        return !$this->sendConfigService->isWithinSleepTime($robotInfo->main_uid,$robotId,SendConfigConstants::ROOM_WELCOME,true);
    }

    /**
     * 获取发送内容
     * @param $cfg
     * @return array
     */
    private function getSendMessageData($cfg): array
    {
        switch ($cfg['send_type']){
            case 1:
                //随机一条
                $data = [$cfg['send_message'][array_rand($cfg['send_message'])]];
                break;
            case 2:
                //随机一组
                $groupMessage = $cfg['group_message'][array_rand($cfg['group_message'])];
                $data = $groupMessage['message'];
                break;
            default:
                //按照顺序发送全部
                $data = $cfg['send_message'];
                break;
        }
        return $data;
    }

    /**
     * 获取符合当前条件的客户群
     * @param $robotId
     * @param $activeRoom
     * @return array
     */
    private function getSchemeRoomWxids($robotId,$activeRoom,$mainUid): array
    {
        $type = $activeRoom['type'];
        if($type == 0){
            //所有群
            $roomList = $this->roomMapper->getRobotRoomList($robotId);
            $roomWxidList = collect($roomList)->pluck('room_wxid')->toArray();
        }elseif($type == 1){
            //指定的群
            $roomWxidList = collect($activeRoom['room'])->filter(function ($item) use ($robotId){
                return $item['robot_id'] == $robotId;
            })->map(function ($item){
                return $item['room_wxids'];
            })->first();

            if(empty($roomWxidList)){
                return [];
            }else{
                return $roomWxidList;
            }

        }else{
            //按条件筛选
            $cond = $activeRoom['cond'];
            $cond['robot_id'] = $robotId;
            $cond['main_uid'] = $mainUid;
            $cond['uid'] = $mainUid;
            $condRoomList = $this->roomMapper->getRoomList($cond);
            $roomWxidList = collect($condRoomList)->pluck('room_wxid')->toArray();
        }
        return $roomWxidList;
    }
}